package dataStore;

import java.io.IOException;
import java.rmi.RemoteException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;


import tool.GetProper;
import tool.GetInfoByPath;
import tool.MysqlApi;
import dataStruct.DataStoreTask;
import dataStruct.DataStoreTaskBag;
import dataStruct.EnumHeartBeatType;
import dataStruct.FtpFileDowndedCount;
import dataStruct.FtpServerInfo;
import dataStruct.User;
import ftp.FtpApi;

public class UserDataStoreApi implements UserDataStoreApiInterface{
	public UserDataStoreApi( 
			Queue<DataStoreTask> dataStoreTaskChunkQueue,
			Map<String, DataStoreTaskBag> dataStoreTaskSlaverChunkMap,
			Queue<String> dataStoreTaskSlaverChunkQueue,
			Map<String,  FtpFileDowndedCount> ftpFileDownedSizeMap
			)throws SQLException
	{
		UserDataStoreApi.masterProper = GetProper.get_properties("conf/config.ini");
		UserDataStoreApi.blockSize = Long.parseLong(masterProper.getProperty("blockSize"));
		UserDataStoreApi.blockCopy = Long.parseLong(masterProper.getProperty("blockCopy"));		
		UserDataStoreApi.ftpServerInfo = new FtpServerInfo(masterProper);
		
		UserDataStoreApi.state = MysqlApi.create_statement();
		
		UserDataStoreApi.dataStoreTaskChunkQueue = dataStoreTaskChunkQueue;
		UserDataStoreApi.dataStoreTaskSlaverChunkMap =dataStoreTaskSlaverChunkMap ;
		UserDataStoreApi.dataStoreTaskSlaverChunkQueue = dataStoreTaskSlaverChunkQueue;
		UserDataStoreApi.ftpFileDownedSizeMap = ftpFileDownedSizeMap;
	}
	
	
	/****************************************user data storeApi**************************************************************/
	@Override
	public FtpServerInfo get_ftp_server_info() throws RemoteException {
		return ftpServerInfo;
	}

	public Boolean login(User user) throws RemoteException , SQLException{
		//if(true) return true;
		String query = String.format("select count(*) from user_info where user_name='%s' and user_pwd='%s';", user.name, user.password) ;
		try {
			ResultSet resultSet= state.executeQuery(query);
			if((resultSet.next()) && (resultSet.getInt(1) == 1))
			{
				System.out.println("user:[" +user.name +"] login success");
				return true;
			}
			else
			{
				System.out.println("user:[" +user.name +"] login failed");
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("your access database error:" + query);
		}
		return  false;
	}

	public Boolean insert_file_info(String fileMd5, long fileSize)
			throws RemoteException, SQLException {
		String insertFileInfo = String.format("insert  into file_info (file_md5, file_size)  values('%s',   '%s');", fileMd5, (new Long(fileSize)).toString());
		if(state.executeUpdate(insertFileInfo) == 1)
			return true;
		System.out.println("your access mysql error:" + insertFileInfo);
		return false;
	}

	@Override
	public Boolean insert_user_file(String userName, String masterPath, String fileMd5)
			throws RemoteException, SQLException {
		int lastMark;
		if ((lastMark = masterPath.lastIndexOf('/')) == -1) {
			System.out.println("masterPath is not legal : " + masterPath);
			return false;
		}
		
		String fileName;
		if((fileName = GetInfoByPath.get_fileName_by_path(masterPath, lastMark)) == null)
			return false;
		
		masterPath = masterPath.substring(0, lastMark);
		String currentDirId;
		if((currentDirId = 	GetInfoByPath.get_currentDirId_by_path(state, userName,  masterPath)) == null)
		{
			System.out.println(String.format("get currentDirId by path[%s] error (UserDataStoreApi.java)", masterPath));
			return null;
		}
			//debug
//			System.out.println(String.format("userDataStoreApi.java: \tcurrentDirId = %s", currentDirId));
			String countFileName = String.format("select file_name from user_file where user_name='%s' and parent_dir_id ='%s' order by file_name ;",
					userName,  currentDirId);
			
			//debug
//			System.out.println(String.format("userDataStoreApi.java: \tcountFileName = %s", countFileName));
			
			ResultSet resultSet = state.executeQuery(countFileName);

			String notUsedFilename = fileName;
			while(resultSet.next())
			{
				if(notUsedFilename == resultSet.getString(1))
				{
					int lastMark1;
					if((lastMark1 = notUsedFilename.indexOf("(")) != -1)
					{
						String sNum = notUsedFilename.substring(lastMark1 + 1, notUsedFilename.length() - 1);
						Integer num = Integer.parseInt(sNum) + 1;
						notUsedFilename = notUsedFilename.substring(0, lastMark1);
						notUsedFilename += ("(" + num.toString() + ")");
					}
					else
						notUsedFilename += "(1)";
				}
				else
					break;
			}
			
			//debug
//			System.out.println(String.format("userDataStoreApi.java: \tnotUsedFilename = %s",notUsedFilename ));
			String insertUserFileSql = String.format("insert into user_file (user_name, file_name, parent_dir_id, file_md5) values ('%s', '%s', '%s', '%s')",
						userName, notUsedFilename, currentDirId, fileMd5);
			
			//debug
//			System.out.println(String.format("userDataStoreApi.java: \tnot insertUserFileSql = %s",insertUserFileSql ));
			if(state.executeUpdate(insertUserFileSql) != 1)
			{
				System.out.println("your access mysql error : " + insertUserFileSql);
				return false;
			}
			
			//debug
//			System.out.println(String.format("userDataStoreApi.java: \t update user file sueccess" ));
			return true;
	}

	@Override
	public Boolean update_userCount_fileInfo(String fileMd5, long num) throws SQLException {
		return MysqlApi.update_userCount_fileInfo(state, fileMd5, num);
	}

	@Override
	public Boolean md5_exist(String fileMd5) throws RemoteException, SQLException {
		String selectFileInfo = String.format("select count(*) from file_info where file_md5='%s' ;", fileMd5);
		ResultSet resultSet = state.executeQuery(selectFileInfo);
		if(resultSet.next() && (resultSet.getInt(1) == 1))
			return true;
		else
			return false;
	}

	public Boolean split_download(String ftpFilePath) throws RemoteException, SQLException {
		String fileMd5 = ftpFilePath.substring(ftpFilePath.lastIndexOf('/') + 1);
		String selectFileInfo = String.format("select file_size from file_info where file_md5='%s';", fileMd5);
		
		//debug
		System.out.println(String.format("selectFileInfo = %s (UserDataStoreApi.java)", selectFileInfo));
		ResultSet resultSet = state.executeQuery(selectFileInfo);
		
		Long fileSize = new Long(0);
		if(resultSet.next())
			fileSize = resultSet.getLong(1);
		
		FtpServerInfo ftpInfo = new FtpServerInfo(ftpServerInfo);
		ftpInfo.ftpServerPath += "/" + fileMd5;		

	     FtpFileDowndedCount ftpFileDowndedCount = new FtpFileDowndedCount();
	     ftpFileDowndedCount.remainSize = blockCopy * fileSize;
		ftpFileDownedSizeMap.put(ftpInfo.ftpServerPath, ftpFileDowndedCount);
		
		Long offset = new Long(0);
		while(offset < fileSize)
		{
			DataStoreTask dataStoreTask = new  DataStoreTask();
			dataStoreTask.ftpServerInfo = ftpInfo;
			
			dataStoreTask.offset = offset;
			if(offset + blockSize < fileSize)
				dataStoreTask.size = blockSize;
			else
				dataStoreTask.size = fileSize - offset;
			System.out.println(String.format("dataStoreTask.offset = %d, dataTaskStore.size=%d(UserDataStoreApi.java)", dataStoreTask.offset, dataStoreTask.size));
			if((dataStoreTask.chunkId = MysqlApi.insert_chunk_info(state, fileMd5, dataStoreTask.offset, dataStoreTask.size)) == null)
				return false;
			
			//QueueLock.dataStoreTaskChunkLock.lock();
			dataStoreTask.heartBeatType =EnumHeartBeatType.RESPONSE_DOWNLOAD_FILE;
			dataStoreTask.totalSize = fileSize;
			dataStoreTaskChunkQueue.offer(dataStoreTask); 
			//QueueLock.dataStoreTaskChunkLock.unlock();
			
			offset += blockSize;
		}
//		System.out.println(String.format("dataStoreTaskChunkQueue.lenth = %d(UserDataStoreApi.java)", dataStoreTaskChunkQueue.size()));
		return true;
	}
	
	public FtpServerInfo get_ftpServerInfo_by_Path(String userName, String masterPath)throws SQLException, IOException{

		//debug
		System.out.println("******************I have get in*********************************(UserDataStoreApi.java)");
		
		int lastMark;
		if ((lastMark = masterPath.lastIndexOf('/')) == -1) {
			System.out.println("masterPath is not legal : " + masterPath);
			return null;
		}
		
		String fileName;
		if((fileName = GetInfoByPath.get_fileName_by_path(masterPath, lastMark)) == null){
			System.out.println("masterPath is not legal : " + masterPath + "(UserDataStoreApi.java)");
			return null;
		}
		//debug
		System.out.println("downloading fileName is: " + fileName + "(UserDataStoreApi.java)");
		
		masterPath = masterPath.substring(0, lastMark);
		String currentDirId;
		if((currentDirId = 	GetInfoByPath.get_currentDirId_by_path(state, userName,  masterPath)) == null)
		{
			System.out.println(String.format("get currentDirId by path[%s] error (UserDataStoreApi.java)", masterPath));
			return null;
		}
		//debug
		System.out.println("file`s parentDirId is: " + currentDirId + "(UserDataStoreApi.java)");
		
		String fileMd5;
		if(( fileMd5 = MysqlApi.get_fileMd5_by_parentDirId_and_fileName(state, currentDirId, fileName)) == null)
		{
			System.out.println(String.format(" MysqlApi.get_fileMd5_by_parentDirId_and_fileName(state, %s, %s))  error (UserDataStoreApi.java)", currentDirId, fileName ));
			return null;
		}
		//debug
		System.out.println("file`s md5 is: " + fileMd5 + "(UserDataStoreApi.java)");
		
		FtpServerInfo ftpInfo = new FtpServerInfo(ftpServerInfo);
		ftpInfo.ftpServerPath += "/" + fileMd5;	
		FtpApi ftpApi = new FtpApi();  
		ftpApi.connect(
       		ftpServerInfo.ftpServerAdress, 
       		ftpServerInfo.ftpServerPort,
       		ftpServerInfo.ftpServerUser,
       		ftpServerInfo.ftpServerPassword
       		);
		if(ftpApi.has_fileNamePath(ftpInfo.ftpServerPath) == true) 	
		{
			System.out.println(ftpInfo.ftpServerPath + " has exsit at ftpServer (UserDataStoreApi.java)");
			return ftpInfo;
		}
		//debug
		System.out.println(ftpInfo.ftpServerPath + " not has exsit at ftpServer (UserDataStoreApi.java)");
		
		MysqlApi.upload_to_ftp(state, fileMd5, ftpInfo, dataStoreTaskSlaverChunkMap, dataStoreTaskSlaverChunkQueue);
		
		//debug
		System.out.println("upload " +masterPath + " to " +  ftpInfo.ftpServerPath  +  "has finished (UserDataStoreApi.java)");
		
		return ftpInfo;
	}
	public FtpServerInfo wordcount_get_ftpServerInfo_by_Path(String userName, String masterPath)throws SQLException, IOException{

		//debug
		System.out.println("******************I have get in*********************************(UserDataStoreApi.java)");
		
		int lastMark;
		if ((lastMark = masterPath.lastIndexOf('/')) == -1) {
			System.out.println("masterPath is not legal : " + masterPath);
			return null;
		}
		
		String fileName;
		if((fileName = GetInfoByPath.get_fileName_by_path(masterPath, lastMark)) == null){
			System.out.println("masterPath is not legal : " + masterPath + "(UserDataStoreApi.java)");
			return null;
		}
		//debug
		System.out.println("downloading fileName is: " + fileName + "(UserDataStoreApi.java)");
		
		masterPath = masterPath.substring(0, lastMark);
		String currentDirId;
		if((currentDirId = 	GetInfoByPath.get_currentDirId_by_path(state, userName,  masterPath)) == null)
		{
			System.out.println(String.format("get currentDirId by path[%s] error (UserDataStoreApi.java)", masterPath));
			return null;
		}
		//debug
		System.out.println("file`s parentDirId is: " + currentDirId + "(UserDataStoreApi.java)");
		
		String fileMd5;
		if(( fileMd5 = MysqlApi.get_fileMd5_by_parentDirId_and_fileName(state, currentDirId, fileName)) == null)
		{
			System.out.println(String.format(" MysqlApi.get_fileMd5_by_parentDirId_and_fileName(state, %s, %s))  error (UserDataStoreApi.java)", currentDirId, fileName ));
			return null;
		}
		//debug
		System.out.println("file`s md5 is: " + fileMd5 + "(UserDataStoreApi.java)");
		
		FtpServerInfo ftpInfo = new FtpServerInfo(ftpServerInfo);
		ftpInfo.ftpServerPath += "/" + fileMd5;	
		FtpApi ftpApi = new FtpApi();  
		ftpApi.connect(
       		ftpServerInfo.ftpServerAdress, 
       		ftpServerInfo.ftpServerPort,
       		ftpServerInfo.ftpServerUser,
       		ftpServerInfo.ftpServerPassword
       		);
		if(ftpApi.has_fileNamePath(ftpInfo.ftpServerPath) == true) 	
		{
			System.out.println(ftpInfo.ftpServerPath + " has exsit at ftpServer (UserDataStoreApi.java)");
			return ftpInfo;
		}
		//debug
		System.out.println(ftpInfo.ftpServerPath + " not has exsit at ftpServer (UserDataStoreApi.java)");
		
		return ftpInfo;
	}

	public FtpServerInfo map(String userName, String masterPath) throws SQLException, IOException {
		// TODO Auto-generated method stub
		//debug
		System.out.println("******************I have get in*********************************(UserDataStoreApi.java)");
		
		int lastMark;
		if ((lastMark = masterPath.lastIndexOf('/')) == -1) {
			System.out.println("masterPath is not legal : " + masterPath);
			return null;
		}
		
		String fileName;
		if((fileName = GetInfoByPath.get_fileName_by_path(masterPath, lastMark)) == null){
			System.out.println("masterPath is not legal : " + masterPath + "(UserDataStoreApi.java)");
			return null;
		}
		//debug
		System.out.println("downloading fileName is: " + fileName + "(UserDataStoreApi.java)");
		
		masterPath = masterPath.substring(0, lastMark);
		String currentDirId;
		if((currentDirId = 	GetInfoByPath.get_currentDirId_by_path(state, userName,  masterPath)) == null)
		{
			System.out.println(String.format("get currentDirId by path[%s] error (UserDataStoreApi.java)", masterPath));
			return null;
		}
		//debug
		System.out.println("file`s parentDirId is: " + currentDirId + "(UserDataStoreApi.java)");
		
		String fileMd5;
		if(( fileMd5 = MysqlApi.get_fileMd5_by_parentDirId_and_fileName(state, currentDirId, fileName)) == null)
		{
			System.out.println(String.format(" MysqlApi.get_fileMd5_by_parentDirId_and_fileName(state, %s, %s))  error (UserDataStoreApi.java)", currentDirId, fileName ));
			return null;
		}
		//debug
		System.out.println("file`s md5 is: " + fileMd5 + "(UserDataStoreApi.java)");
		
		FtpServerInfo ftpInfo = new FtpServerInfo(ftpServerInfo);
		ftpInfo.ftpServerPath += "/" + fileMd5 + ".wordcount";	
		FtpApi ftpApi = new FtpApi();  
		ftpApi.connect(
       		ftpServerInfo.ftpServerAdress, 
       		ftpServerInfo.ftpServerPort,
       		ftpServerInfo.ftpServerUser,
       		ftpServerInfo.ftpServerPassword
       		);
		if(ftpApi.has_fileNamePath(ftpInfo.ftpServerPath) == true) 	
		{
			System.out.println(ftpInfo.ftpServerPath + " has exsit at ftpServer (UserDataStoreApi.java)");
			return ftpInfo;
		}
		//debug
		System.out.println(ftpInfo.ftpServerPath + " not has exsit at ftpServer (UserDataStoreApi.java)");
		
		MysqlApi.wordcount_upload_to_ftp(state, fileMd5, ftpInfo, dataStoreTaskSlaverChunkMap, dataStoreTaskSlaverChunkQueue);
		
		//debug
		System.out.println("upload " +masterPath + " to " +  ftpInfo.ftpServerPath  +  "has finished (UserDataStoreApi.java)");
		
		return ftpInfo;
	}
	
	private static FtpServerInfo ftpServerInfo ;
	private static Properties masterProper;
	private static Statement state;
	private static Long blockCopy;
	private static Long blockSize;
	
	private static Queue<DataStoreTask> dataStoreTaskChunkQueue;
	private static Map<String, DataStoreTaskBag> dataStoreTaskSlaverChunkMap;
	private static Queue<String> dataStoreTaskSlaverChunkQueue;
	private static Map<String, FtpFileDowndedCount> ftpFileDownedSizeMap;
}
